Skip to content

ci: add least-privilege permissions to GitHub Actions workflows#6545

Open
peter-matkovski wants to merge 18 commits into
developfrom
ci/workflow-least-privilege-permissions
Open

ci: add least-privilege permissions to GitHub Actions workflows#6545
peter-matkovski wants to merge 18 commits into
developfrom
ci/workflow-least-privilege-permissions

Conversation

@peter-matkovski

@peter-matkovski peter-matkovski commented Jul 6, 2026

Copy link
Copy Markdown

Goal

Add least-privilege permissions blocks to GitHub Actions workflows to resolve CodeQL actions/missing-workflow-permissions alerts (APPSEC-164).

Implementation

  • Add explicit workflow-level permissions blocks across GitHub Actions workflows.
  • Default to read-only scopes (contents: read, pull-requests: read).
  • Grant write scopes only where jobs need them (artifacts, Danger, release git push).

Testing

  • CI green on this PR
  • Code scanning alerts close after merge

Restrict default GITHUB_TOKEN scope per workflow. Write scopes granted only
where jobs dispatch/cancel workflows, publish packages, or label issues/PRs.

Refs: APPSEC-164
@peter-matkovski peter-matkovski requested a review from a team as a code owner July 6, 2026 10:05
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

PR checklist ❌

The following issues were detected:

  • Missing required label: at least one label starting with pr:.
  • Section Goal is missing or empty.
  • Section Implementation is missing or empty.
  • Section Testing is missing or empty.

What we check

  1. Title is concise (5–18 words) unless labeled pr:ignore-for-release.
  2. At least one pr: label exists (e.g., pr:bug, pr:new-feature).
  3. Sections ### Goal, ### Implementation, and ### Testing contain content. Bot-authored PRs are exempt.
  4. PR description references an issue (Linear ticket like AND-123, a Linear URL, or a GitHub Closes #N). Bot-authored PRs are exempt.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.93 MB 5.93 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.20 MB 11.20 MB 0.00 MB 🟢
stream-chat-android-compose 12.67 MB 12.67 MB 0.00 MB 🟢

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR adds explicit workflow-level permissions blocks to fourteen GitHub Actions workflow files. Most workflows now declare read-only access to contents and/or pull-requests, while two automation workflows (no-response, sdk-size-updates) declare write access to issues/pull-requests. No job logic, steps, or triggers are otherwise modified.

Changes

GitHub Actions permissions hardening

Layer / File(s) Summary
Read-only permissions declarations
.github/workflows/apk-s3-distribute.yml, .github/workflows/app-distribute-v7.yml, .github/workflows/app-distribute.yml, .github/workflows/build-and-test.yml, .github/workflows/clean-detekt-baseline.yaml, .github/workflows/e2e-build.yml, .github/workflows/e2e-test-backend.yml, .github/workflows/e2e-test-cron.yml, .github/workflows/e2e-test.yml, .github/workflows/pr-checks.yml, .github/workflows/publish-new-version.yml, .github/workflows/snapshot-test.yaml
Each workflow adds a top-level permissions block granting read-only access, most commonly contents: read, and in some cases also pull-requests: read.
Write-scoped permissions for automation
.github/workflows/no-response.yml, .github/workflows/sdk-size-updates.yml
The no-response workflow grants issues: write and pull-requests: write; the sdk-size-updates workflow grants pull-requests: write.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Estimated code review effort: 1 (Trivial) | ~5 minutes

Poem

Fourteen burrows, tokens tight,
Each workflow locked down just right.
Read for most, write for a few,
A rabbit's audit, through and through.
Hop, hop, ship it — permissions all in view! 🐇🔒

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed Clearly summarizes the main change: adding least-privilege permissions to GitHub Actions workflows.
Description check ✅ Passed Covers Goal, Implementation, and Testing, but omits several template sections like UI Changes, checklists, and GIF.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/workflow-least-privilege-permissions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/build-and-test.yml:
- Around line 13-16: The workflow YAML has an invalid indentation in the
permissions block, causing the file to fail parsing. Fix the permissions section
in the build-and-test workflow so that pull-requests: read is aligned as a
sibling of contents: read, not nested under it. Use the permissions mapping near
the top of the workflow as the reference point and ensure the YAML structure is
valid for GitHub Actions and actionlint/yamllint.

In @.github/workflows/clean-detekt-baseline.yaml:
- Around line 8-11: The workflow YAML is invalid because `pull-requests: read`
is indented under `contents: read` instead of being a sibling permission entry.
Fix the permissions block in the workflow so the `permissions` mapping has
separate `contents` and `pull-requests` keys at the same indentation level,
matching the valid pattern used elsewhere in the repo.

In @.github/workflows/no-response.yml:
- Around line 10-13: The workflow YAML has invalid indentation in the
permissions block, causing the file to fail parsing. Fix the permissions mapping
so pull-requests is aligned as a sibling of issues in the no-response workflow,
and verify the workflow remains valid YAML after the indentation correction.

In @.github/workflows/pr-checks.yml:
- Around line 9-12: The workflow permissions block has invalid YAML because
pull-requests: read is indented as a child of contents: read instead of a
sibling entry. Fix the permissions mapping in pr-checks.yml so contents and
pull-requests are aligned under permissions, using the existing permissions
block near the workflow top-level.

In @.github/workflows/snapshot-test.yaml:
- Around line 18-21: The workflow YAML is invalid because the permissions block
in snapshot-test.yaml has incorrect indentation, causing parse failures. Update
the permissions mapping so pull-requests: read is aligned as a sibling of
contents: read under the permissions section, and verify the workflow remains
valid for actionlint and yamllint.
- Around line 18-21: The workflow permissions are too restrictive for the
snapshot creation step. Update the permissions block used by the
`peter-evans/create-pull-request@v8` step in the snapshot test workflow so
`GITHUB_TOKEN` has write access, specifically `contents: write` and
`pull-requests: write`, instead of read-only access. Keep the change scoped to
the workflow permissions section associated with the create-pull-request job.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4603db61-7b03-4c74-905b-d396730793fd

📥 Commits

Reviewing files that changed from the base of the PR and between 48f5ab2 and 38d3fd6.

📒 Files selected for processing (14)
  • .github/workflows/apk-s3-distribute.yml
  • .github/workflows/app-distribute-v7.yml
  • .github/workflows/app-distribute.yml
  • .github/workflows/build-and-test.yml
  • .github/workflows/clean-detekt-baseline.yaml
  • .github/workflows/e2e-build.yml
  • .github/workflows/e2e-test-backend.yml
  • .github/workflows/e2e-test-cron.yml
  • .github/workflows/e2e-test.yml
  • .github/workflows/no-response.yml
  • .github/workflows/pr-checks.yml
  • .github/workflows/publish-new-version.yml
  • .github/workflows/sdk-size-updates.yml
  • .github/workflows/snapshot-test.yaml

Comment thread .github/workflows/build-and-test.yml Outdated
Comment on lines +13 to +16
permissions:
contents: read
pull-requests: read

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Invalid YAML — workflow will fail to parse.

pull-requests: read is over-indented under contents: read, which is not valid YAML (a scalar value cannot have a nested mapping). Confirmed by both actionlint and yamllint. This breaks the entire workflow file at parse time.

🐛 Proposed fix
 permissions:
   contents: read
-    pull-requests: read
+  pull-requests: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
pull-requests: read
permissions:
contents: read
pull-requests: read
🧰 Tools
🪛 actionlint (1.7.12)

[error] 15-15: could not parse as YAML: mapping values are not allowed in this context

(syntax-check)

🪛 YAMLlint (1.37.1)

[error] 15-15: syntax error: mapping values are not allowed here

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-and-test.yml around lines 13 - 16, The workflow YAML
has an invalid indentation in the permissions block, causing the file to fail
parsing. Fix the permissions section in the build-and-test workflow so that
pull-requests: read is aligned as a sibling of contents: read, not nested under
it. Use the permissions mapping near the top of the workflow as the reference
point and ensure the YAML structure is valid for GitHub Actions and
actionlint/yamllint.

Source: Linters/SAST tools

Comment on lines +8 to +11
permissions:
contents: read
pull-requests: read

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Invalid YAML — workflow will fail to parse.

Same indentation defect as in build-and-test.yml: pull-requests: read is nested under the scalar contents: read, which is invalid YAML. Confirmed by actionlint/yamllint.

🐛 Proposed fix
 permissions:
   contents: read
-    pull-requests: read
+  pull-requests: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
pull-requests: read
permissions:
contents: read
pull-requests: read
🧰 Tools
🪛 actionlint (1.7.12)

[error] 10-10: could not parse as YAML: mapping values are not allowed in this context

(syntax-check)

🪛 YAMLlint (1.37.1)

[error] 10-10: syntax error: mapping values are not allowed here

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/clean-detekt-baseline.yaml around lines 8 - 11, The
workflow YAML is invalid because `pull-requests: read` is indented under
`contents: read` instead of being a sibling permission entry. Fix the
permissions block in the workflow so the `permissions` mapping has separate
`contents` and `pull-requests` keys at the same indentation level, matching the
valid pattern used elsewhere in the repo.

Source: Linters/SAST tools

Comment thread .github/workflows/no-response.yml Outdated
Comment on lines +10 to +13
permissions:
issues: write
pull-requests: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Invalid YAML indentation breaks the entire workflow.

pull-requests: write is nested under issues: write instead of being a sibling mapping key. actionlint and yamllint both report could not parse as YAML: mapping values are not allowed in this context at this line, which will prevent the workflow from parsing/running at all.

🔧 Fix indentation
 permissions:
   issues: write
-    pull-requests: write
+  pull-requests: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
issues: write
pull-requests: write
permissions:
issues: write
pull-requests: write
🧰 Tools
🪛 actionlint (1.7.12)

[error] 12-12: could not parse as YAML: mapping values are not allowed in this context

(syntax-check)

🪛 YAMLlint (1.37.1)

[error] 12-12: syntax error: mapping values are not allowed here

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/no-response.yml around lines 10 - 13, The workflow YAML
has invalid indentation in the permissions block, causing the file to fail
parsing. Fix the permissions mapping so pull-requests is aligned as a sibling of
issues in the no-response workflow, and verify the workflow remains valid YAML
after the indentation correction.

Source: Linters/SAST tools

Comment thread .github/workflows/pr-checks.yml Outdated
Comment on lines +9 to +12
permissions:
contents: read
pull-requests: read

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Invalid YAML indentation breaks the entire workflow.

pull-requests: read is nested under contents: read instead of being a sibling mapping key, which is invalid YAML. Static analysis confirms this: actionlint reports could not parse as YAML: mapping values are not allowed in this context and yamllint reports a matching syntax error. This will cause the whole workflow to fail to run.

🔧 Fix indentation
 permissions:
   contents: read
-    pull-requests: read
+  pull-requests: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
pull-requests: read
permissions:
contents: read
pull-requests: read
🧰 Tools
🪛 actionlint (1.7.12)

[error] 11-11: could not parse as YAML: mapping values are not allowed in this context

(syntax-check)

🪛 YAMLlint (1.37.1)

[error] 11-11: syntax error: mapping values are not allowed here

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-checks.yml around lines 9 - 12, The workflow
permissions block has invalid YAML because pull-requests: read is indented as a
child of contents: read instead of a sibling entry. Fix the permissions mapping
in pr-checks.yml so contents and pull-requests are aligned under permissions,
using the existing permissions block near the workflow top-level.

Source: Linters/SAST tools

Comment thread .github/workflows/snapshot-test.yaml Outdated
Comment on lines +18 to +21
permissions:
contents: read
pull-requests: read

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Invalid YAML indentation breaks the entire workflow.

pull-requests: read is nested under contents: read rather than being a sibling key. actionlint and yamllint both flag could not parse as YAML: mapping values are not allowed in this context at this line.

🔧 Fix indentation
 permissions:
   contents: read
-    pull-requests: read
+  pull-requests: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
pull-requests: read
permissions:
contents: read
pull-requests: read
🧰 Tools
🪛 actionlint (1.7.12)

[error] 20-20: could not parse as YAML: mapping values are not allowed in this context

(syntax-check)

🪛 YAMLlint (1.37.1)

[error] 20-20: syntax error: mapping values are not allowed here

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/snapshot-test.yaml around lines 18 - 21, The workflow YAML
is invalid because the permissions block in snapshot-test.yaml has incorrect
indentation, causing parse failures. Update the permissions mapping so
pull-requests: read is aligned as a sibling of contents: read under the
permissions section, and verify the workflow remains valid for actionlint and
yamllint.

Source: Linters/SAST tools


🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the workflow around the referenced lines.
if [ -f .github/workflows/snapshot-test.yaml ]; then
  nl -ba .github/workflows/snapshot-test.yaml | sed -n '1,140p'
fi

# Look for the create-pull-request action usage in this workflow.
rg -n "create-pull-request|record ==|permissions:|pull-requests:|contents:" .github/workflows/snapshot-test.yaml || true

Repository: GetStream/stream-chat-android

Length of output: 207


🏁 Script executed:

#!/bin/bash
set -euo pipefail

if [ -f .github/workflows/snapshot-test.yaml ]; then
  sed -n '1,140p' .github/workflows/snapshot-test.yaml
fi

printf '\n--- matches ---\n'
rg -n "create-pull-request|record ==|permissions:|pull-requests:|contents:" .github/workflows/snapshot-test.yaml || true

Repository: GetStream/stream-chat-android

Length of output: 2277


🌐 Web query:

peter-evans/create-pull-request@v8 permissions contents write pull-requests write default GITHUB_TOKEN documentation

💡 Result:

To use peter-evans/create-pull-request@v8 with the default GITHUB_TOKEN, you must explicitly elevate the token's permissions in your workflow file [1][2]. For repositories created after February 2, 2023, the default GITHUB_TOKEN permissions are read-only, which prevents the action from creating or updating pull requests [3][1]. To grant the necessary access, include the following permissions block in your workflow job [1][2]: permissions: contents: write pull-requests: write Additionally, you must ensure that GitHub Actions is permitted to create pull requests in your repository settings. Navigate to your repository's Settings > Actions > General > Workflow permissions and ensure that "Allow GitHub Actions to create and approve pull requests" is enabled [1][2][4]. Important considerations: - Forked repositories: If a workflow is triggered by a pull request from a fork, the GITHUB_TOKEN will have read-only access regardless of your permission settings [5][6][7]. In such cases, the action will fail to create pull requests [6][7]. - Triggering further workflows: Pull requests created by the default GITHUB_TOKEN will not trigger subsequent on: push or on: pull_request workflows [1][6]. If you require downstream workflows to run automatically, you must use a Personal Access Token (PAT) or a GitHub App token instead [1][8][2].

Citations:


Grant write access for create-pull-request

peter-evans/create-pull-request@v8 runs with the default GITHUB_TOKEN here, so record: true needs contents: write and pull-requests: write; read will cause that step to fail.

🔧 Suggested permissions
 permissions:
-  contents: read
-  pull-requests: read
+  contents: write
+  pull-requests: write
🧰 Tools
🪛 actionlint (1.7.12)

[error] 20-20: could not parse as YAML: mapping values are not allowed in this context

(syntax-check)

🪛 YAMLlint (1.37.1)

[error] 20-20: syntax error: mapping values are not allowed here

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/snapshot-test.yaml around lines 18 - 21, The workflow
permissions are too restrictive for the snapshot creation step. Update the
permissions block used by the `peter-evans/create-pull-request@v8` step in the
snapshot test workflow so `GITHUB_TOKEN` has write access, specifically
`contents: write` and `pull-requests: write`, instead of read-only access. Keep
the change scoped to the workflow permissions section associated with the
create-pull-request job.

Comment thread .github/workflows/e2e-test-cron.yml Fixed
@peter-matkovski peter-matkovski added the pr:ci CI changes label Jul 7, 2026
@peter-matkovski peter-matkovski enabled auto-merge (squash) July 7, 2026 19:34
@sonarqubecloud

sonarqubecloud Bot commented Jul 8, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:ci CI changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants